import pygame, random
import math, sys

#The class for the player. A block that moves with hitboxes attached to it.
class player(object):
	def __init__(self):
		self.surf = pygame.Surface((40,40))
		self.surf.fill((255*random.random(),255*random.random(),255*random.random()))
		self.rect = pygame.Rect(0,0,25,25)
		self.rect.topleft = (50,50)
		
		self.right = False			#'Right' key is held
		self.canmoveright = False	#Player can move right
		self.left = False
		self.canmoveleft = False
		
		self.down = True		#Player is falling down
		
		self.jump = False		#Player Presses space
		self.injump = False		#Player is in a jump (moving upward)
		self.holdjump = 0		#Variable that counts upward. Makes sure that if the player holds down space, they will not walljump after jumpin'
		self.hold = False		#Variable that, when true, adds to 'holdjump'
		self.walljumptimer = 0
		
		self.speed = 0
		self.downforce = 0
		self.jumpforce = 7
		
	def move(self):
		self.rect.move_ip(self.speed,0)
		
		#If on ground, handle like this.
		if self.injump == False and self.down == False:
			if self.canmoveright == True:
				if self.right == True:
					if self.speed < 3:
						self.speed += .5
			if self.canmoveleft == True:
				if self.left == True:
					if self.speed > -3:
						self.speed -= .5
			if self.left == False and self.right == False:
				if self.speed > 0:
					self.speed -= .5
				if self.speed < 0:
					self.speed += .5
		
		#If in air, handle like tihs.
		if self.injump == True or self.down == True:
			if self.canmoveright == True:
				if self.right == True:
					if self.speed < 3:
						self.speed += .1
			if self.canmoveleft == True:
				if self.left == True:
					if self.speed > -3:
						self.speed -= .1
			
		#If falling, apply downforce that grows with time and stops at 4.
		if self.down == True and self.injump == False:
			if self.downforce < 4:
				self.downforce += .2
				self.walljumptimer = 20
			self.rect.move_ip(0,self.downforce)
			

		#If not jumping, activate jump!
		if self.injump == False and self.down == False:
			if self.jump == True:
				self.injump = True
				
		#If jumping, apply these forces:
		if self.injump == True:
			if self.jumpforce > 0:
				self.down == False
				self.rect.move_ip(0,-self.jumpforce)	
				self.jumpforce -= .2
				
		#If there is no jumpforce left, take the player out of jump mode.
		if self.jumpforce <= 0:
				self.injump = False
		
		#These two If statements make it so you slide slower while going up or down a wall
		if (self.canmoveright == False or self.canmoveleft == False) and self.injump == True:
			self.jumpforce -= .05
		if (self.canmoveright == False or self.canmoveleft == False) and self.down == True:
			if self.downforce > .15:
				self.downforce -= .15
		
		
		#Test if the player is able to walljump based on a timer
		if self.walljumptimer > 10:
			self.canwalljump = True
		else:
			self.canwalljump = False
			
		if self.walljumptimer < 20:
			self.walljumptimer += 1
			

		#Execute the walljump if player is in position
		if self.canwalljump == True  and self.holdjump == 0:
			if (self.canmoveright == False or self.canmoveleft == False) and (self.down == True or self.injump == True):
				if self.jump == True:
					self.injump = True
					self.jumpforce = 7
					if self.canmoveright == False:
						self.speed -= 3.5
					if self.canmoveleft == False:
						self.speed += 3.5
		#Holdin jump key
		if self.hold == True:
			self.holdjump = 1
		else:
			self.holdjump = 0

#Player's right movement hitbox	
class rhitbox(object):
	def __init__(self):
		self.surf = pygame.Surface((10,20))
		self.surf.fill((255*random.random(),255*random.random(),255*random.random()))
		self.rect = pygame.Rect(0,0,10,20)
		self.rect.topleft = (50,50)
	def move(self,x,y):
		self.rect.topright = (x,y)

#Player's left movement hitbox	
class lhitbox(object):
	def __init__(self):
		self.surf = pygame.Surface((10,20))
		self.surf.fill((255*random.random(),255*random.random(),255*random.random()))
		self.rect = pygame.Rect(0,0,10,20)
		self.rect.topleft = (50,50)
	def move(self,x,y):
		self.rect.topright = (x,y)		
	
#Player's bottom movement hitbox		
class bhitbox(object):
	def __init__(self):
		self.surf = pygame.Surface((20,10))
		self.surf.fill((255*random.random(),255*random.random(),255*random.random()))
		self.rect = pygame.Rect(0,0,10,20)
		self.rect.topleft = (50,50)
	def move(self,x,y):
		self.rect.topright = (x,y)		

#Test Platforms		
class platform(object):
	def __init__(self):
		self.surf = pygame.Surface((200,20))
		self.surf.fill((255*random.random(),255*random.random(),255*random.random()))		
		self.rect = pygame.Rect(0,0,200,20)
		self.rect.topleft = (40,500)
		
#Test Wall		
class wall(object):
	def __init__(self):
		self.surf = pygame.Surface((200,300))
		self.surf.fill((255*random.random(),255*random.random(),255*random.random()))		
		self.rect = pygame.Rect(0,0,200,300)
		self.rect.topleft = (500,100)


class Game(object):
	def __init__(self):
		#800 x 600 because i don't know what i should use.
		self.screen = pygame.display.set_mode((800, 600))
		self.gameover = False
		self.clock = pygame.time.Clock()
		
		#Initiate all class objects
		self.player = player()
		self.platform = platform()
		self.platform2 = platform()
		self.wall = wall()
		self.rhitbox = rhitbox()
		self.lhitbox = lhitbox()
		self.bhitbox = bhitbox()
		
		self.platform2.rect.topleft = (300,400)

	def process_input(self):
		for event in pygame.event.get():
			if event.type == pygame.KEYDOWN:
				if event.key == pygame.K_ESCAPE:
					self.gameover = True
				if event.key == pygame.K_RIGHT:
					self.player.right = True
				if event.key == pygame.K_LEFT:
					self.player.left = True
				if event.key == pygame.K_SPACE:
					self.player.hold = True
					self.player.jump = True
					if self.player.injump == False:
						self.player.jumpforce = 7		#This number is important. It decides how fast the player moves upwards in a jump.
						self.player.walljumptimer = 0
						
			if event.type == pygame.KEYUP:
				if event.key == pygame.K_RIGHT:
					self.player.right = False
				if event.key == pygame.K_LEFT:
					self.player.left = False
				if event.key == pygame.K_SPACE:
					self.player.jump = False
					self.player.hold = False
					self.player.jumpforce /= 2		#Halving this number when spacebar is released makes it so that the player may control the height of their jumps.
					
							
	def update(self):
		self.player.move()
		
		#Place hitboxes
		self.rhitbox.move(self.player.rect.right + 20,self.player.rect.top + 10)
		self.lhitbox.move(self.player.rect.right - 20,self.player.rect.top + 10)
		self.bhitbox.move(self.player.rect.right - 5,self.player.rect.top + 35)
		
		#Test for rhitbox and wall colliding
		if not self.rhitbox.rect.colliderect(self.wall):
			self.player.canmoveright = True
		else:
			self.player.canmoveright = False
			if self.player.speed > 0:
				self.player.speed -= 1
			
		#Test for lhitbox and wall colliding
		if not self.lhitbox.rect.colliderect(self.wall):
			self.player.canmoveleft = True
		else:
			self.player.canmoveleft = False
			if self.player.speed < 0:
				self.player.speed += 1
		
		#Test for hitbox and floor colliding
		if not self.bhitbox.rect.colliderect(self.platform) and not self.bhitbox.rect.colliderect(self.platform2):
			self.player.down = True
		else:
			self.player.down = False
			self.player.downforce = 0
	
	def draw(self):
		self.screen.fill((100,20,100))
		self.screen.blit(self.player.surf,self.player.rect)
		self.screen.blit(self.platform.surf,self.platform.rect)
		self.screen.blit(self.platform2.surf,self.platform2.rect)
		self.screen.blit(self.wall.surf,self.wall.rect)
		self.screen.blit(self.rhitbox.surf,self.rhitbox.rect)
		self.screen.blit(self.lhitbox.surf,self.lhitbox.rect)
		self.screen.blit(self.bhitbox.surf,self.bhitbox.rect)
		
pygame.init()
g = Game()

while not g.gameover:
	g.clock.tick(60)
	g.process_input()
	g.update()
	g.draw()
	pygame.display.flip()

sys.exit()
	